/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.openharmony.recyclercomponent;

import com.ohos.MotionEvent;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DragInfo;
import ohos.agp.render.Canvas;
import ohos.agp.utils.Rect;
import ohos.app.Context;

/**
 * ContainerGroup
 */
public class ContainerGroup extends ComponentContainer implements Component.DrawTask, Component.DraggedListener {
    private int mCurrentScrollX = 0;

    private int mCurrentScrollY = 0;

    private float x;

    private float y;

    /**
     * constructor
     *
     * @param context Context
     */
    public ContainerGroup(Context context) {
        super(context);
        setup();
    }

    /**
     * constructor
     *
     * @param context Context
     * @param attrSet AttrSet
     */
    public ContainerGroup(Context context, AttrSet attrSet) {
        super(context, attrSet);
        setup();
    }

    /**
     * constructor
     *
     * @param context   Context
     * @param attrSet   AttrSet
     * @param styleName String
     */
    public ContainerGroup(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet);
        setup();
    }

    /**
     * constructor
     *
     * @param context      Context
     * @param attrs        AttrSet
     * @param defStyleAttr int
     * @param defStyleRes  int
     */
    public ContainerGroup(Context context, AttrSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, null);
        setup();
    }

    public ContainerGroup(Context context, AttrSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        automate(component, canvas);
    }

    @Override
    public void scrollTo(int x, int y) {
        int xx, yy;
        xx = x - mCurrentScrollX;
        yy = y - mCurrentScrollY;
        //this should be set before scrollby for working scroll when not overriding scroll by
        mCurrentScrollX = x;
        mCurrentScrollY = y;
        scrollBy(-xx, -yy);
    }

    public void removeAllViews() {
        super.removeAllComponents();
    }

    public final Context getContext() {
        return super.mContext;
    }

    public int getPaddingTop() {
        return super.getPaddingTop();
    }

    public int getPaddingBottom() {
        return super.getPaddingBottom();
    }

    public int getPaddingLeft() {
        return super.getPaddingLeft();
    }

    public int getPaddingStart() {
        return super.getPaddingStart();
    }

    public int getPaddingRight() {
        return super.getPaddingRight();
    }

    public int getPaddingEnd() {
        return super.getPaddingEnd();
    }

    public final int getWidth() {
        return super.getWidth();
    }

    public final int getHeight() {
        return super.getHeight();
    }

    public final void offsetDescendantRectToMyCoords(Component descendant, Rect rect) {
        offsetRectBetweenParentAndChild(descendant, rect, true, false);
    }

    public final void offsetRectIntoDescendantCoords(Component descendant, Rect rect) {
        offsetRectBetweenParentAndChild(descendant, rect, false, false);
    }

    protected LayoutConfig generateDefaultLayoutParams() {
        return super.getLayoutConfig();
    }

    public LayoutConfig generateLayoutParams(AttrSet attrs) {
        super.setLayoutConfig(new LayoutConfig(getContext(), attrs));
        return super.getLayoutConfig();
    }

    protected LayoutConfig generateLayoutParams(LayoutConfig p) {
        super.setLayoutConfig(new LayoutConfig(p));
        return super.getLayoutConfig();
    }

    public Component getChildAt(int i) {
        return super.getComponentAt(i);
    }

    public void addView(Component child, int index, LayoutConfig lp) {
        super.addComponent(child, index, lp);
    }

    public void addView(Component child, int index) {
        super.addComponent(child, index);
    }

    public void removeView(Component view) {
        super.removeComponent(view);
    }

    public void removeViewAt(int index) {
        super.removeComponentAt(index);
    }

    public int getChildCount() {
        return super.getChildCount();
    }
    //-------------------------------------------------------------------------------------------------------

    //not exact match - may cause problems
    public final int getMeasuredHeight() {
        return super.getHeight();
    }

    public final int getMeasuredWidth() {
        return getWidth();
    }

    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
        super.setWidth(measuredWidth);
        super.setHeight(measuredHeight);
    }

    protected boolean checkLayoutParams(LayoutConfig p) {
        return super.verifyLayoutConfig(p) == p;
    }

    public void requestLayout() {
        super.invalidate();
        super.requestFocus();
    }

    public void requestChildFocus(Component child, Component focused) {
        focused.requestFocus();
    }

    public Component focusSearch(Component v, int direction) {
        super.findRequestNextFocus(direction);
        v.findFocus();
        return v;
    }

    private void setup() {
        addDrawTask(this);
        setClickable(true);
        setDraggedListener(1, this);
    }

    private void automate(Component component, Canvas canvas) {
        onMeasure(component.getWidth(), component.getHeight());
        onAttachedToWindow();
        draw(canvas);
        onDraw(canvas);
        onLayout(true, super.getLeft(), super.getTop(), super.getRight(), super.getBottom());
    }

    public void scrollBy(int x, int y) {
        super.scrollTo(mCurrentScrollX, mCurrentScrollY);
    }
    //--------------------------------------------------------------------------------------------------------------

    //Callbacks - should override
    protected void onAttachedToWindow() {
    }

    protected void onDetachedFromWindow() {
    }

    protected void onLayout(boolean changed, int l, int t, int r, int b) {
    }

    protected void onMeasure(int widthSpec, int heightSpec) {
    }

    public void draw(Canvas c) {
    }

    public void onDraw(Canvas c) {
    }
    //-------------------------------------------------------------------------------------------------------

    //from here , Not defined
    public boolean requestChildRectangleOnScreen(Component child, Rect rectangle, boolean immediate) {
        return false;
    }

    public void postInvalidateOnAnimation(ContainerGroup v) {
    }

    public boolean onInterceptTouchEvent(MotionEvent e) {
        return false;
    }

    public void postOnAnimation(ContainerGroup v, Runnable r) {
    }

    public boolean onTouchEvent(MotionEvent e) {
        return false;
    }

    public boolean removeCallbacks(Runnable action) {
        return true;
    }

    public void setWillNotDraw(boolean m) {
    }

    void offsetRectBetweenParentAndChild(Component descendant, Rect rect, boolean offsetFromChildToParent,
                                         boolean clipToBounds) {
    }

    @Override
    public void onDragDown(Component component, DragInfo dragInfo) {
    }

    @Override
    public void onDragStart(Component component, DragInfo dragInfo) {
        x = dragInfo.startPoint.position[0];
        y = dragInfo.startPoint.position[1];
    }

    @Override
    public void onDragUpdate(Component component, DragInfo dragInfo) {
        float DeltaX = x - dragInfo.updatePoint.position[0], DeltaY = y - dragInfo.updatePoint.position[1];
        scrollBy((int) DeltaX, (int) DeltaY);
    }

    @Override
    public void onDragEnd(Component component, DragInfo dragInfo) {
    }

    @Override
    public void onDragCancel(Component component, DragInfo dragInfo) {
    }
}
